package my.download;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

import wxg.utils.ContentTypeAndExtension;
import wxg.utils.My;

/**
 * 
 * 基于"apache httpclient"
 * 
 * @author Wxg
 *
 */
public class DownloadByHttpClient {

	private static int id = 1;
	
	private static final String SP = File.separator;
	
	private String dir = My.prop("mainconf.properties").getProperty("DownloadStore");
	
	private FileNameFrom fileNameFrom = FileNameFrom.date;
	
	public static enum FileNameFrom{
		url, date
	}
	
	public DownloadByHttpClient(){}
	
	public DownloadByHttpClient(FileNameFrom fileNameFrom){
		this.fileNameFrom = fileNameFrom;
	}
	
	public DownloadByHttpClient(FileNameFrom fileNameFrom, String dirKey){
		this.fileNameFrom = fileNameFrom;
		this.dir = My.prop("mainconf.properties").getProperty(dirKey);
	}
	
	public void download(final String url){
		// String url = "http://img.hb.aicdn.com/778466793fd1fd8801ecb60e85801296c98b3844459bd-G41ZnT_fw658";
		
		HttpGet get = new HttpGet(url);
		
		/**
		 * 参考: http://blog.csdn.net/u011179993/article/details/47150145
		 * Add at 2018年1月29日
		 * 
		 */
		get.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0");
		
		/**
		 * 参考: http://blog.csdn.net/h254532699/article/details/54342470
		 * Add at 2018年1月29日
		 */
		RequestConfig conf = null;
		conf = RequestConfig.custom()
				.setConnectTimeout(5000)
				.setConnectionRequestTimeout(1000)
				.setSocketTimeout(5000)
				.build();
		
		
		CloseableHttpClient client = HttpClients.createDefault();
		get.setConfig(conf);
		
		try {
			client.execute(get, new ResponseHandler<String>(){
				@Override
				public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
					int status = response.getStatusLine().getStatusCode();
					if (status >= 200 && status < 300) {
						HttpEntity entity = response.getEntity();
						File file = null;
						switch (fileNameFrom){
							case url:
								file = obtainOutputFileAddress(entity, url);
								break;
							case date:
							default:
								file = obtainOutputFileAddress(entity);
								break;
						}
						InputStream is = entity.getContent();
						BufferedInputStream bis = new BufferedInputStream(is);
						BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
						byte[] buffer = new byte[1024];
						int len = 0;
						try {
							while( (len = bis.read(buffer)) != -1 ){
								bos.write(buffer, 0, len);
							}
						} finally {
							bos.close();
							// bis.close(); // client.close(); >> bis will close?!
						}
						
					}
					return null;
				}
			});
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				client.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 将文件目录和文件名称及扩展名拼接起来
	 * -	* 文件名称是随机的,由日期和数字组合而成
	 * 
	 * 
	 * @param entity
	 * @return
	 */
	private File obtainOutputFileAddress(HttpEntity entity){
		String str = dir + SP + My.ss(id++) + getExtensionFromContentType(entity);
		return new File(str);
	}
	
	/**
	 * 将文件目录和文件名称及扩展名拼接起来
	 * -	* 文件名称从URL提取
	 * 
	 * @param entity
	 * @param url
	 * @return
	 */
	private File obtainOutputFileAddress(HttpEntity entity, String url){
		String str = dir + SP + optUrlGetFileName(url) + getExtensionFromContentType(entity);
		return new File(str);
	}
	
	/**
	 * 从"ContenType"中提取出文件扩展名
	 * @param entity
	 * @return
	 */
	private String getExtensionFromContentType(HttpEntity entity){
		ContentTypeAndExtension cte = new ContentTypeAndExtension();
		String contentType = entity.getContentType().getValue();
		String ext = cte.getSingleExtensions(contentType);
		return ext;
	}
	
	/**
	 * 提取URL中的filename
	 * 
	 * @param url
	 * @return
	 */
	private String optUrlGetFileName(String url){
		String aa = url.substring(url.lastIndexOf("/")+1);
		if(aa.contains(".")){
			aa = aa.substring(0, aa.lastIndexOf("."));
		}
		return aa;
	}
	
	/**
	 * 加了"User-Agent"和"timeout",还是下载不了"seleniumhq"上的图片了;
	 * 估计"seleniumhq"采取了新的措施,不允许程序直连下载图片;
	 * 或者是"httpClient"的频繁短连接给他们的服务器造成了压力,他们将此种方式的连接屏蔽了！
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		DownloadByHttpClient dbc = new DownloadByHttpClient();
		String[] urls = new String[]{
				"http://img.hb.aicdn.com/778466793fd1fd8801ecb60e85801296c98b3844459bd-G41ZnT_fw658",
				"http://www.seleniumhq.org/docs/_images/chapt3_img01_IDE_Installation.png"
		};
		for(String url : urls){
			dbc.download(url);
		}
//		dbc.download(urls[0]);
	}
	
}
